package com.example.alphabetindexer.widget;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.widget.SectionIndexer;

/**
 * SectionIndexer
 * @author atearsan/2013年8月4日
 *
 */
public class AlphabetSectionIndexer implements SectionIndexer {
	private String OTHER = "#";
	private String[] mSections = { OTHER, "A", "B", "C" , "D", "E" ,"F", "G" , "H" , "I", 
			"J", "K", "L", "M" , "N" , "O", "P" ,"Q" ,"R" ,"S" , 
			"T" ,"U" , "V", "W", "X", "Y", "Z"  } ;

	private int OTHER_INDEX = 0 ; // index of other in the mSections array
	
	
	private int[] mPositions; // store the list of starting position index for each section
							  // e.g. A start at index 0, B start at index 20, C start at index 41 and so on
	private List<Integer> positionsList = new ArrayList<Integer>();

	private int mCount; // this is the count for total number of contacts
	
	// Assumption: the contacts array has been sorted
	public AlphabetSectionIndexer(List<AlphabetIndexerBean> beanList) {
		mCount = beanList.size();
		
		initPositions(beanList);
		
//		for(int i = 0 ; i < mSections.length ; i++){
//			Log.i("ContactSectionIndexer", "Letter: " + mSections[i] + ", pos: " + mPositions[i] );
//		}
	}
	
	/**
	 * 如果List数据集改变(比如搜索的时候就会使用过滤后的List), 这里也必须改变, 不然indexer和改变后的List对应不上<br>
	 * 现在是在{@link AlphabetIndexerAdapter#notifyDataSetChanged()}里调用的. 已经封装好.
	 * @author atearsan/2013-08-06
	 * @param beanList
	 */
	public void notifyBeanListChanged(List<AlphabetIndexerBean> beanList) {
		mCount = beanList.size();
		
		initPositions(beanList);
	}
	
	/**
	 * 取title
	 * @author atearsan/2013-08-02
	 * @param section
	 * @return
	 */
	public String getSectionTitle(int section) {
		section = positionsList.get(section);
		int i = 0;
		for(int val : mPositions) {
			if(val >= section) break;
			i++;
		}
		return mSections[i];
	}
	
	public String getSectionTitle(String indexableItem){
		int sectionIndex = getSectionIndex(indexableItem);
		return mSections[sectionIndex];
	}
	
	// return which section this item belong to
	public int getSectionIndex(String indexableItem){
		if( indexableItem == null )
		{
			return OTHER_INDEX;
		}
		
		indexableItem = indexableItem.trim();
		String firstLetter = OTHER;
		
		if(indexableItem.length() == 0){
			return OTHER_INDEX;
		}
		else
		{
			// get the first letter
			firstLetter = String.valueOf(indexableItem.charAt(0) ).toUpperCase();
		}
		
		int sectionCount = mSections.length;
		for(int i = 0 ; i < sectionCount ; i++ ){
			if( mSections[i].equals(firstLetter) )
			{
				return i;
			}
		}
		
		return OTHER_INDEX;
		
	}
	
	// initialize the position index
	public void initPositions(List<AlphabetIndexerBean> beanList)  {
		
		int sectionCount = mSections.length;
		mPositions = new int[sectionCount];
		
		Arrays.fill(mPositions, -1); // initialize everything to -1
		
		// Assumption: list of items have already been sorted by the prefer names
		int itemIndex = 0;
		
		for(AlphabetIndexerBean bean: beanList){
			
			String indexableItem = bean.getSortKey();
			// 字母对应的下标
			int sectionIndex = getSectionIndex(indexableItem); // find out which section this item belong to
			
			/*
			 * atearsan/2013-08-02 
			  导航表:
			 [#, A, B, C, D, E, F, G, H, I, J,  K,  L,  M,  N,  O,  P,  Q,  R,  S,  T,  U,  V,  W,  X,  Y,  Z]
			 
			 // TODO 提供测试数据
			  示例mPositions结果: mPositions长度为27, 对应导航表
			 [0, 0, 0, 0, 3, 3, 4, 4, 4, 4, 5,  7,  8,  8,  8,  8,  11, 11, 11, 12, 16, 16, 16, 17, 18, 18, 19]
			  则结果表示: listview中的分组是
			 [#, #, #, #, D, D, F, F, F, F, J,  K,  L,  L,  L,  L,  P,  P,  P,  S,  T,  T,  T,  W,  X,  Y,  Z]
			 
			 itemIndex对应的数字表示数据在list里的下标开始位置
			 
			 这地方看不懂的需要自己建少量联系人数据调试才能理解
			 */
			if(mPositions[sectionIndex] == -1) // if not set before, then do this, otherwise just ignore
				mPositions[sectionIndex] = itemIndex;
			
			itemIndex++;
			
		}
		
		
		int lastPos = -1;
		
		// now loop through, for all the ones not found, set position to the one before them
		// this is to make sure the array is sorted for binary search to work
		for(int i = 0; i < sectionCount; i++){
			if( mPositions[i] == -1)
				mPositions[i] = lastPos;
			
			lastPos = mPositions[i];
			
			positionsList.add(mPositions[i]); // atearsan/2013-08-02
		}
	}


	@Override
	public int getPositionForSection(int section) {
		if (section < 0 || section >= mSections.length) {
            return -1;
        }

        return mPositions[section];
	}

	@Override
	public int getSectionForPosition(int position) {
		if (position < 0 || position >= mCount ) {
            return -1;
        }

        int index = Arrays.binarySearch(mPositions, position);

        /*
         * Consider this example: section positions are 0, 3, 5; the supplied
         * position is 4. The section corresponding to position 4 starts at
         * position 3, so the expected return value is 1. Binary search will not
         * find 4 in the array and thus will return -insertPosition-1, i.e. -3.
         * To get from that number to the expected value of 1 we need to negate
         * and subtract 2.
         */
        
        return index >= 0 ? index : -index - 2;
	}

	@Override
	public Object[] getSections() {
		return mSections;
	}
	
	// if first item in section, then return the section
	// otherwise return -1
	public boolean isFirstItemInSection(int position){ // check whether this item is the first item in section
		int section = Arrays.binarySearch(mPositions, position);
		return (section > -1);
	 
	}
	
} // End. SectionIndexer
